package server_service

/**
* @author aFun
* @data 2025/4/10 01:24
* @email: afunaaa222@163.com / 1030935903
* @address: Guangdong University of Technology, China
 */

import (
	"camp_lucky_draw/entity"
	"camp_lucky_draw/server"
	"camp_lucky_draw/server/common"
	"camp_lucky_draw/server/data"
	"camp_lucky_draw/server/util"
	"camp_lucky_draw/transfer"
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
)

func Do_draw(role *entity.Role, Args map[string]interface{}) error {

	tx := server.DB.Begin()
	if tx.Error != nil {
		return fmt.Errorf("tx.Error: %v", tx.Error)
	}
	// TODO: 差了个功能：保底次数必升层
	err := do_check(
		role, Args,
		check_is_open,
		check_lev,
		check_is_end,
		check_is_at_max_floor,
		check_loss,
		do_up_or_down,
		do_change_floor,
		update,
		push)

	if err != nil {
		tx.Rollback()
		return err
	}

	if err = tx.Save(&role).Error; err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return err
}

func do_check(role *entity.Role, Args map[string]interface{}, checks ...CheckFunc) error {
	for _, check := range checks {
		if err := check(role, Args); err != nil {
			return err
		}
	}
	return nil
}

func check_is_open(role *entity.Role, Args map[string]interface{}) error {
	//CampId := server.CampId
	//CD := server.CampaignData[CampId]
	//currentTime := time.Now()
	//timestamp := currentTime.Unix()
	//if timestamp < CD.StartTime {
	//	return errors.New("活动未开启")
	//} else if timestamp > CD.EndTime {
	//	return errors.New("活动已结束")
	//}
	return nil
}

func check_lev(role *entity.Role, Args map[string]interface{}) error {
	if role.Lev <= 40 {
		return errors.New("等级过低")
	}
	return nil
}

func check_is_end(role *entity.Role, Args map[string]interface{}) error {
	if role.Lucky_draw.Is_end {
		return errors.New("本轮已经结束啦，请领取完奖励开启下一轮")
	}
	return nil
}

func check_is_at_max_floor(role *entity.Role, Args map[string]interface{}) error {
	curFloor := role.Lucky_draw.Cur_floor
	if curFloor >= data.GetFloorMax {
		return errors.New("已经达到最高层啦，请领取完奖励再开启新一轮")
	}
	return nil
}

// 检查消耗是否充足
// 充足则执行消耗
func check_loss(role *entity.Role, Args map[string]interface{}) error {
	CurFloor := role.Lucky_draw.Cur_floor
	Consumed := 0
	IsProtected, _ := Args["is_protected"].(bool)
	if IsProtected {
		Consumed = int(data.GetConstCfgById[common.CommonConsumed["Protected"][CurFloor]].(float64))
	} else {
		Consumed = int(data.GetConstCfgById[common.CommonConsumed["Normal"][CurFloor]].(float64))
	}
	// TODO:暂时假设身上没有任何代币，只能通过消耗资产来消耗
	ConsumedPer := int(data.GetConstCfgById[common.TokenConsumed].(float64))
	RoleAsset := role.Asset
	if RoleAsset < int64(ConsumedPer*Consumed) {
		return errors.New("资产不足")
	} else {
		role.Asset -= int64(ConsumedPer * Consumed)
		Args["consumed_tokens"] = Consumed
		return nil
	}
}

// 判断执行结果是升层还是降层
func do_up_or_down(role *entity.Role, Args map[string]interface{}) error {
	CurFloor := role.Lucky_draw.Cur_floor
	Data, _ := data.GetLayerCfgByFloor[CurFloor]
	WeightedPro := map[string]int{
		"up_pro":   int(Data["upWeight"].(float64)),
		"down_pro": int(Data["downWeight"].(float64)),
	}
	Result := util.Random_by_weight(WeightedPro)
	Args["pro_result"] = Result
	return nil
}

func do_change_floor(role *entity.Role, Args map[string]interface{}) error {
	Result := Args["pro_result"].(string)
	Data := server.CampLuckyDrawData[Result].([]interface{})
	var WeightPro map[string]int = make(map[string]int)
	for _, item := range Data {
		d := item.(map[string]interface{})
		tmp := d["result"].(float64)
		WeightKey := strconv.Itoa(int(tmp))
		WeightPro[WeightKey] = int(d["weight"].(float64))
	}
	ChageResult := util.Random_by_weight(WeightPro)
	Args["change_result"] = ChageResult
	return nil
}

// 更新LuckyDraw的数据
func update(role *entity.Role, Args map[string]interface{}) error {
	var ld entity.LuckyDraw = role.Lucky_draw
	ChangeResult, _ := strconv.Atoi(Args["change_result"].(string))
	if Args["pro_result"] == "up_pro" {
		// 升层
		ld.Cur_floor += int8(ChangeResult)
		ld.Prev_change = int8(ChangeResult)
	} else if Args["pro_result"] == "down_pro" {
		// 降层
		ld.Prev_change = -int8(ChangeResult)
		IsProtected, _ := Args["is_protected"].(bool)
		if !IsProtected {
			ld.Cur_floor = max(0, ld.Cur_floor-int8(ChangeResult))
			ld.Is_end = true
		}
	} else {
		return errors.New("参数有误！")
	}
	// 更新累计抽取次数
	ld.Draw_num += 1
	ld.Consumed_tokens += int64(Args["consumed_tokens"].(int))
	role.Lucky_draw = ld

	return nil
}

// 推送基础更新
func push(role *entity.Role, Args map[string]interface{}) error {
	conn := server.OnlineUserMgr.OnlineIdConn[role.ID]

	if conn == nil {
		return errors.New("连接异常")
	}

	// 开始推送数据
	LuckyDrawData := role.Lucky_draw
	ldData, err := json.Marshal(LuckyDrawData)
	if err != nil {
		return err
	}
	resMes := entity.Msg{
		Code:          27200,
		Status:        true,
		Repsonse_data: string(ldData),
	}
	dataRes, err := json.Marshal(resMes)
	if err != nil {
		return err
	}
	tf := &transfer.Transfer{
		Conn: conn,
	}
	err = tf.WritePkg(dataRes)
	if err != nil {
		return err
	}
	return nil

}
